package com.example.demo2.test.factory;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.ConnectionPool;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;

import java.io.IOException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * websocket连接工厂
 * 
 * @author yusong
 *
 */
@Slf4j
public class ConnectionFactory {
	// 判断是否把数据放入队列
	private static boolean LATENCY_DEBUG_SWATCH = Boolean.FALSE;
	// 有界阻塞队列
	private static LinkedBlockingQueue<NetworkLatency> LATENCY_DEBUG_QUEUE = new LinkedBlockingQueue<>();
	// 创建一个最大空闲连接数为20，最大空闲连接时间为300s的连接池
	private static ConnectionPool connectionPool = new ConnectionPool(20, 300, TimeUnit.SECONDS);
	// 创建一个网络连接客户端
	private static final OkHttpClient client = new OkHttpClient.Builder().followSslRedirects(false)
			.followRedirects(false).connectTimeout(5000, TimeUnit.MILLISECONDS).readTimeout(5000, TimeUnit.MILLISECONDS)
			.writeTimeout(5000, TimeUnit.MILLISECONDS).connectionPool(connectionPool)
			.addNetworkInterceptor(new Interceptor() {
				@Override
				public Response intercept(Chain chain) throws IOException {
					Request request = chain.request();

					Long startNano = System.nanoTime();

					Response response = chain.proceed(request);

					Long endNano = System.nanoTime();

					if (LATENCY_DEBUG_SWATCH) {
						LATENCY_DEBUG_QUEUE.add(new NetworkLatency(request.url().url().getPath(), startNano, endNano));
					}
					return response;
				}
			}).build();
	
	public static String execute(Request request) {

		Response response = null;
		String str = null;
		try {
			log.debug("[Request URL]{}", request.url());
			response = client.newCall(request).execute();
			if (response.code() != 200) {
				throw new RuntimeException(
						"[Execute] Response Status Error : " + response.code() + " message:" + response.message());
			}
			if (response != null && response.body() != null) {
				str = response.body().string();
				response.close();
			} else {
				throw new RuntimeException("[Execute] Cannot get the response from server");
			}
			log.debug("[Response]{}", str);
			return str;
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("[Execute] Cannot get the response from server");
		}

	}

	// 创建一个websocket
	public static WebSocket createWebSocket(Request request, WebSocketListener listener) {
		return client.newWebSocket(request, listener);
	}

	// 设置是否把连接放入队列中
	public static void setLatencyDebug() {
		LATENCY_DEBUG_SWATCH = Boolean.TRUE;
	}

	// 获取队列
	public static LinkedBlockingQueue<NetworkLatency> getLatencyDebugQueue() {
		return LATENCY_DEBUG_QUEUE;
	}

	// 清理队列中的数据
	public static void clearLatencyDebugQueue() {
		LATENCY_DEBUG_QUEUE.clear();
	}

	@Data
	@Builder
	@AllArgsConstructor
	@NoArgsConstructor
	public static class NetworkLatency {

		private String path;

		private Long startNanoTime;

		private Long endNanoTime;
	}
}
